<!--
 * @Author: Penk
 * @LastEditors: Penk
 * @LastEditTime: 2023-10-13 10:31:10
 * @FilePath: \web-interview-questions\路由\history路由.html
 * @email: 492934056@qq.com
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
  <title>Document</title>
  <style>
    button+button {
      margin-left: 20px;
    }

    .codeBox {
      background-color: black;
      padding: 10px;
      color: white;
    }
  </style>
</head>

<body style="margin-top: 50px; margin-left: 50px">
  <main>
    <button id="pushStateBtn">pushState跳转，监听不了</button>
    <button id="replaceStateBtn">replaceState跳转，监听不了</button>
    <button id="goBtn">go(0)跳转，如果没有配置会返回404</button>
    <button id="backBtn">back跳转，popstate监听到了</button>
    <button id="forwardBtn">forward跳转，popstate监听到了</button>
    <button id="gotoHome">跳转到首页，测试用</button>

    <br />
    <span style="color: red; font-size: 12px">打开控制台可以看数据</span>

    <p>history的监听：</p>
    <div class="codeBox">
      <code>
          window.addEventListener("popstate", (e) => {
          <br />
          &nbsp;&nbsp; console.log("onpopstate:", e, location.pathname);
          <br />
          });
          <br />
          // history.replaceState()，以及history.pushState() 需要重写
          <br />
          let rawReplace = history.replaceState;
          <br />
          history.replaceState = (...arg) => {
          <br />
          &nbsp;&nbsp; rawReplace.apply(history, arg);
          <br />
          &nbsp;&nbsp; console.log("replaceState change...");
          <br />
          }
          <br />
          <br />

          let rawPush = history.pushState;
          <br />
          history.pushState = (...arg) => {
          <br />
          &nbsp;&nbsp; rawPush.apply(history, arg);
          <br />
          &nbsp;&nbsp; console.log("pushState change...");
          <br />
          }
          <br />
        </code>
    </div>

    <p>history的变化方式：</p>
    <ul>
      <li>通过浏览器的前进后退方式</li>
      <li>JS的方式 history.pushState() 切换路由前的url会保存在history中，并不会出发popstate</li>
      <li>
        JS的方式 history.replaceState() 切换路由前的url不会保存在history中，并不会出发popstate
      </li>
      <li>
        JS的方式 go()方法可以在用户的历史记录中任意跳转。
        这个方法接收一个参数，表示向后或向前跳转的页面数的一个整数值。
        负数表示向后跳转(类似于后退按钮)，正数表示向前跳转(类似于前进按钮)。 history.go(0)等于刷新
      </li>
      <li>JS的方式 back()方法用于模仿浏览器的后退按钮，相当于history.go(-1)，可以出发popstate</li>
      <li>
        JS的方式 forward()方法用于模仿浏览器的前进按钮，相当于history.go(1)，可以出发popstate
      </li>
    </ul>

    <p>特点：</p>
    <ul>
      <li>hash 能兼容到IE8， history 只能兼容到 IE10。</li>
      <li>hash 本来是拿来做页面定位的，如果拿来做路由的话，原来的锚点功能就不能用了。</li>
      <li>如果后台没有配置，刷新可能导致404。</li>
      <li>
        hash 的传参是基于 url 的，如果要传递复杂的数据，会有体积的限制，而 history
        模式不仅可以在url里放参数，还可以将数据存放在一个特定的对象中。
      </li>
    </ul>
  </main>

  <script>
    // 监听history模式
    // 只能监听history.go、histroy.back()、history.forward()
    window.addEventListener('popstate', (e) => {
      console.log('onpopstate:', e, location.pathname)
    })
    // history.replaceState()，以及history.pushState() 需要重写
    let rawReplace = history.replaceState
    history.replaceState = (...arg) => {
      rawReplace.apply(history, arg)
      console.log('replaceState change...')
    }

    let rawPush = history.pushState
    history.pushState = (...arg) => {
      rawPush.apply(history, arg)
      console.log('pushState change...')
    }

    $('#pushStateBtn').click((e) => {
      let name = 'user' + Math.floor(Math.random() * 100)
      const state = {
        name
      }
      history.pushState(state, '', name)
      console.log('执行pushState，并不能触发popstate事件，只有浏览器前进后退才可以。')
    })

    $('#replaceStateBtn').click((e) => {
      history.replaceState(
        {
          name: 'user' + Math.floor(Math.random() * 100)
        },
        null,
        'user' + Math.floor(Math.random() * 100)
      )
      console.log('执行replaceState，并不能触发popstate事件，只有浏览器前进后退才可以。')
    })

    $('#goBtn').click((e) => {
      history.go(0)
    })

    $('#backBtn').click((e) => {
      history.back()
    })

    $('#forwardBtn').click((e) => {
      history.forward()
    })

    let href = window.location.href
    $('#gotoHome').click((e) => {
      location.href = href
    })
  </script>
</body>

</html>